require'zdc.idutil'
require'zdc.sandbox'
require'zdc.ds.filedb'
local fsutil=require'zdc.ds.util'
local isparent=zdc.idutil.IsParent
local PreRemove=zdc.idutil.PreRemove
local conf_do = zdc.sandbox.conf_do
module(..., package.seeall)

ModDB = {}
ModDB_mt ={__metatable = {}, __index = ModDB}

_getdbwherefun=zdc.ds.filedb._getdbwherefun

function new(params)
	local obj = {dir=params[1],rootid=params[2],pre=params[3] or ''}
	if type(obj.rootid)=='string' then obj.rootid={obj.rootid} end
	if #obj.pre>0 then
		obj.pre_=obj.pre..'/'
		obj.premod=obj.pre
	else
		obj.pre_=''
		obj.premod='____'
	end
	setmetatable(obj, ModDB_mt)
	obj:init()
	return obj
end

function ModDB:transdo(fn)
	return fn()
end

function ModDB:deflate_node(a,b,c)
	return zdc.deflate.deflate_node(a,b,c)
end

function ModDB:init()
	self.store={}
	function attrdir (path,prem)
		for file in lfs.dir(path) do
			local sss=file:sub(1,1)
			if sss~='.' and sss~='$' then
				local f = path..'/'..file
				local attr = lfs.attributes (f)
				if attr.mode == "directory" then
					attrdir (f,prem .. file .. '/')
				else
					local k = string.match(file, "^(.+)%.lua$")
					if k then
						self.store[prem .. k] = 1
						print("scan module node",prem .. k)
					end
				end
			end
		end
	end
	if self.rootid then
		for _,rootid in ipairs(self.rootid) do
			local f = self.dir..'/'..rootid..'.lua'
			if lfs.attributes (self.dir..'/'..rootid..'.lua') then
				self.store[self.pre_..rootid] = 1
				print("scan module rootid node",rootid)
			end
			if lfs.attributes(self.dir..'/'..rootid) then
				attrdir (self.dir..'/'..rootid,self.pre_..rootid..'/')
			end
		end
	else
		if lfs.attributes(self.dir) then
			attrdir (self.dir,self.pre_)
		end
	end
end

function ModDB:reset_cache()
	self:init()
end
function ModDB:node_exists(id)
	return self.store[id] ~= nil
	--local path = self.dir.."/"..fsutil.fs_escape_id_but_keep_slash(id)..'.zmd'
	--return fsutil.file_exist(path,id)
end

function ModDB:get_node(id)
	local cc=self.store[id]
	if not cc then return nil end
	if type(cc)=='table' then
		return cc
	end
	
	local deltaid=PreRemove(id,self.pre_)
	assert(deltaid)
	
	local path = self.dir.."/"..deltaid..'.lua'

	local vvv,err = loadfile(path)
	if vvv then
		local mid=string.gsub("___."..id,"/", ".")
		package.loaded[mid]=nil
		vvv,err=pcall(vvv,mid)
		if vvv then
			err=package.loaded[mid]
			package.loaded[mid]=nil
			vvv={data=(err.NODE_DATA or zdc.deflate.deflate_node(err.NODE)),ik=err.ik, ts=err.ts}
			self.store[id]=vvv
		end
	end
	return vvv,err
end

function ModDB:save_node(id,data,ik,ts)
	error('moddb not support save['..id .. ']')
end

ModDB.get_child_nodes=zdc.ds.filedb.FileDB.get_child_nodes
ModDB.get_child_nodes_ex=zdc.ds.filedb.FileDB.get_child_nodes_ex
ModDB.get_nodes_by_prefix=zdc.ds.filedb.FileDB.get_nodes_by_prefix
ModDB.get_nodes_by_prefix_ex=zdc.ds.filedb.FileDB.get_nodes_by_prefix_ex
ModDB.get_ids_by_prefix=zdc.ds.filedb.FileDB.get_ids_by_prefix
ModDB.get_ids_by_prefix_ex=zdc.ds.filedb.FileDB.get_ids_by_prefix_ex
ModDB.get_child_ids=zdc.ds.filedb.FileDB.get_child_ids
ModDB.get_child_ids_ex=zdc.ds.filedb.FileDB.get_child_ids_ex
ModDB.get_cnt_by_prefix=zdc.ds.filedb.FileDB.get_cnt_by_prefix
ModDB.get_cnt_by_prefix_ex=zdc.ds.filedb.FileDB.get_cnt_by_prefix_ex
ModDB.get_child_cnt=zdc.ds.filedb.FileDB.get_child_cnt
ModDB.get_child_cnt_ex=zdc.ds.filedb.FileDB.get_child_cnt_ex


function ModDB:del_node(id,deep)
	error('moddb not support del['..id .. ']')
end

function ModDB:del_sub_nodes(parentid)
	error('moddb not support delsub['..id .. ']')
end
function ModDB:get_label(id)
	error('moddb not support get_label')
end

function ModDB:set_label(id, idx,sum,timestamp,usr)
	error('moddb not support set_label')
end

function ModDB:get_nodes_sum(rootid, sumfun)
	return sumfun(nil,rootid,'')
end